package com.powergisol.gis.controller;

import com.alibaba.fastjson.JSONObject;
import com.powergisol.gis.service.*;
import com.powergisol.gis.vo.*;
import feign.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping(value = "gis")
public class MapDescriptionController {
    private static Logger logger = LoggerFactory.getLogger(MapDescriptionController.class);
    @Autowired
    private TabDataService tabDataService;
    @Autowired
    private FallBackService fallBackService;
    @Autowired
    private TabCoordinateService tabCoordinateService;

    @Autowired
    private WMSService wmsService;

    @Autowired
    private WFSService wfsService;

//    @Value("${layer-ip}")
//    private String layerIp;
//    @Value("${file-url}")
//    private String fileUrl;
//    @Value("${style-url}")
//    private String styleUrl;

    @GetMapping(value = "server/{layerName}")
    public String wmsLayer(@PathVariable(required = false, value = "layerName") String layerName, Model model,String service,
                String bbox, String uuid, String request, String srs, HttpServletResponse httpServletResponse) {
        if(null != service && "WFS".equals(service)){
            if(request.equals("GetFeature")){
                return "forward:wfs/json?layers=" + layerName;
            }
        }else{
            if (bbox != null && uuid != null && request.equals("GetMap")) {
                return "forward:layer?layers=" + layerName;
            }
            if (bbox != null && uuid != null && request.equals("GetFeatureInfo")) {
                return "forward:json?layers=" + layerName;
            }
        }

        String suffix = "html";
        if(null == layerName || layerName.isEmpty()){
            model.addAttribute("detailsData", null);
            return "noMessage";
        }
        String[] split = layerName.split("\\.");
        String name = split[0];
        if (split.length == 2) {
            suffix = split[1];
        }
        TabServiceVo tabService = tabDataService.getVoByName(name);
        if(1 != tabService.getState()){
            model.addAttribute("detailsData", tabService);
            return "noMessage";
        }
        String userDir = System.getProperty("user.dir");
        userDir = userDir.substring(0,userDir.lastIndexOf(File.separator));
        String layer = fallBackService.getLayer(name, tabService.getFileUrl(), userDir+File.separator+"serviceData"+File.separator+"style"+File.separator+ tabService.getStyleUrl(), tabService.getTitle());
        JSONObject jsonObject = JSONObject.parseObject(layer);
        FeatureTypeMap featureType = JSONObject.toJavaObject(jsonObject, FeatureTypeMap.class);

        if(1 != tabService.getState()){
            model.addAttribute("detailsData", tabService);
            return "noMessage";
        }
        model.addAttribute("baseData", featureType);

        if(null == featureType ||null == featureType.getNativeCRS() || null == featureType.getNativeCRS().getWkid()){
            model.addAttribute("proj4js", "");
        }else{
            String epsg = featureType.getNativeCRS().getWkid();
            String str[] = epsg.split(":");
            Map<String,Object> map = tabCoordinateService.selectProByEspg(str[1]);
            model.addAttribute("proj4js", map);
        }
        logger.info("serviceurl={}",tabService.getServiceUrl());
        model.addAttribute("detailsData", tabService);
        switch (suffix) {
            case "xml":
                return "noCreating";
            case "json":
                return "noCreating";
            case "kml":
                return "noCreating";
            case "ol3":
                return "ol";
            case "webgl3d":
                return "map";
            default:
                return "index";
        }
    }

    @ResponseBody
    @GetMapping(value = "getLayerTable/{row}")
    public String shpDetail(@PathVariable(value = "row") int row, String name) {
        TabServiceVo tabService = tabDataService.getVoByName(name);
        String userDir = System.getProperty("user.dir");
        userDir = userDir.substring(0,userDir.lastIndexOf(File.separator));
        String s = fallBackService.getLayerTableDetail(row, name, tabService.getFileUrl(), userDir+File.separator+"serviceData"+File.separator+"style"+File.separator+tabService.getStyleUrl(), tabService.getTitle());
        return s;
    }

    @ResponseBody
    @GetMapping(value = "server/layer", produces = {MediaType.IMAGE_PNG_VALUE})
    public Object getWmsLayer(String layers, String bbox, String uuid, String width, String height,String srs,HttpServletResponse httpServletResponse) {
        String transparent = "true";
        String service = "WMS";
        String version = "1.1.1";
        String request = "GetMap";
        String styles = "";
        String format = "image/jpeg";
        TabServiceVo tabService = tabDataService.getVoByName(layers);

        if(null == tabService || 1 != tabService.getState()){
            return  null;
        }
        if(null == srs || srs.equals("null") || ("").equals(srs)){
            srs = tabService.getServiceCoordinate();
        }

        if (width == null || height == null || width.equals("null") || height.equals("null")) {
            width = "256";
            height = "256";
        }
        Response response = wmsService.getWmsLayerResponse(transparent,service,version,width,height,request,styles,format,layers,bbox,uuid,srs);
        Response.Body body = response.body();
//        InputStream fileInputStream = null;
////        OutputStream outStream = null;
        InputStream fileInputStream = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            fileInputStream = body.asInputStream();
            byte[] bytes = new byte[1024];

            int len = 0;
            while((len = fileInputStream.read(bytes)) != -1) {
                baos.write(bytes, 0, len);
            }
            byte[] buffer = baos.toByteArray();
            fileInputStream.close();
            return buffer;
        } catch (Exception e) {
        }
        return null;
    }

    @ResponseBody
    @GetMapping(value = "server/json", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public Object getWmsJson(String layers, String uuid, String bbox, String x, String y,String srs) {
        String transparent = "true";
        String service = "WMS";
        String version = "1.1.1";
        String request = "GetFeatureInfo";
        String info_format = "application/json";
        String styles = "";
        String width = "256";
        String height = "256";
        TabServiceVo tabService = tabDataService.getVoByName(layers);

        if(1 != tabService.getState()){
            return  null;
        }

        if(null == srs || srs.equals("null") || ("").equals(srs)){
            srs = tabService.getServiceCoordinate();
        }
        String str = wmsService.getWmsLayer(transparent,service,version,width,height,request,styles,info_format,layers,bbox,uuid,srs,x,y);
        if(null != str){
            JSONObject test = JSONObject.parseObject(str);
            return test;
        }
        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("code", -1);
        return resultMap;

    }

    @ResponseBody
    @GetMapping(value = "server/wfs/json", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public Object getWfsJson(String service,String request,String layers, String maxFeatures,String typeName,
                             String typeNames,String version,String startIndex,String outputFormat,String filter) {
        if(!"1.0.0".equals(version)){
            return null;
        }
        TabServiceVo tabService = tabDataService.getVoByName(layers);
        if(1 != tabService.getState()){
            return  null;
        }

        String str = wfsService.getWfs1LayerResponse(service,version,request,null,startIndex,layers,typeNames,maxFeatures,outputFormat,filter);
        if(null != str){
            JSONObject test = JSONObject.parseObject(str);
            return test;
        }
        System.out.println(layers);
        return null;
    }

}
